<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js 运动--链式运动</title>
    <style type="text/css">

body{
    width: 100%;
    height: 300px;
    position: relative;
    overflow: hidden;
}
#div1{
    width: 100px;
    height: 100px;
    background-color: #99CCFF;
    filter: alpha(opacity:30);
    opacity: 0.3;
}

#xx{
    position: absolute;
    bottom: 0;
    right: 0;
    width: 150px;
    height: 250px;
    overflow: hidden;
}

#but{
    width: 50px;
    height: 50px;
    background-color: #99CCFF;
    position: absolute;
    right:0;
    bottom: 0;
    z-index: 99;
}
#bottom{
    width: 100px;
    height: 50px;
    background-color: #FFCCCC;
    position: absolute;
    right:-50px;
    bottom: 0;
    z-index: 9;
}
#box{
    width: 150px;
    height: 200px;
    background-color: #CCCCFF;
    position: absolute;
    bottom: -200px;
    right: 0;
    display: none;
}
#div3, #div4, #div5, #div6{
    width: 100px;
    height: 100px;
    background-color: #FFCCCC;
}
#div4, #div6{
    filter:alpha(opacity:30);
    opacity: 0.3;
}
    </style>
</head>

<body>

<h2>1、链式运动框架</h2>
<div id="div1"></div>

<h2>2、链式运动框架的运用</h2>
<div id="xx">
    <div id="but"></div>
    <div id="bottom"></div>
    <div id="box">
        <i id="btn_close">关</i>
    </div>
</div>

<h2>3、目前的框架存在的问题</h2>
<input type="button" id="btn3" value="move">
<div id="div3"></div>

<h2>4、完美运动框架</h2>
<input type="button" id="btn4" value="move">
<div id="div4"></div>

<h2>5、完美运动框架--问题</h2>
<input type="button" id="btn5" value="move">
<div id="div5"></div>


<h2>6、完美运动框架--问题解决</h2>
<input type="button" id="btn6" value="move">
<div id="div6"></div>




<h2>4、完美运动框架</h2>
<script>

window.onload = function(){
    // 1、链式运动框架
    var oDiv1 = document.getElementById("div1");
    oDiv1.onmouseover = function(){
        move(this, 'width', 300, function(){
            move(oDiv1, 'height', 300, function(){
                move(oDiv1, 'opacity', 100);
            });
        });
    }
    oDiv1.onmouseout = function(){
        move(oDiv1, 'opacity', 30, function(){
            move(oDiv1, 'height', 100, function(){
                move(oDiv1, 'width', 100);
            })
        })
    }


    // 2、链式运动框架的运用
    var oBut = document.getElementById("but");
    var oBottom = document.getElementById("bottom");
    var oBox = document.getElementById("box");
    var oClose = document.getElementById("btn_close");

    oBut.onclick = function(){
        move(oBottom, 'right', 50, function(){
            oBox.style.display = 'block';
            move(oBox, 'bottom', 50);
        });
    }
    oClose.onclick = function(){
        move(oBox, 'bottom', -150, function(){
            oBox.style.display = 'none';
            move(oBottom, 'right', -50);
        })
    }


    // 3、目前的框架存在的问题
    // 问题：不能让物体的好几个属性一起运动
    var btn3 = document.getElementById("btn3");
    var div3 = document.getElementById("div3");
    btn3.onclick = function(){
        move(div3, "width", 200);
        // 只有高度变了，因为变宽的定时器才刚开，变高的定时器立马就把变宽的定时器关闭了
        move(div3, "height", 200);
    }



    // 4、完美运动框架--movePerfect1
    // 可以让物体多个属性一起运动
    var btn4 = document.getElementById("btn4");
    var div4 = document.getElementById("div4");
    btn4.onclick = function(){
        movePerfect1(div4, {"width":200, "height":200, "opacity":100}, function(){
            movePerfect1(div4,{"opacity":30});
        });
    }

    // 5、完美运动框架--movePerfect1
    // 问题
    var btn5 = document.getElementById("btn5");
    var div5 = document.getElementById("div5");
    btn5.onclick = function(){
        movePerfect1(div5, {"width":110, "height":200, "opacity":100});
    }

    // 5、完美运动框架--movePerfect2
    // 问题解决
    var btn6 = document.getElementById("btn6");
    var div6 = document.getElementById("div6");
    btn6.onclick = function(){
        movePerfect2(div6, {"width":101, "height":200, "opacity":100}, function(){
            movePerfect2(div6, {"opacity":30});
        });
    }

}








// ----------------------------------------------------------------------------------

//完美运动框架usage:  movePerfect(oDiv, {"width":400, "height":400}, function(){....});
//问题：一旦发现json的某个属性到达目的地，就把定时器关了
function movePerfect1(obj, json, fnEnd){
    clearInterval(obj.timer);
    obj.timer = setInterval(function(){

        // json的循环用for-in
        for(var attr in json){

            var val = 0;
            if(attr == 'opacity'){
                val = Math.round(parseFloat(getStyle(obj, attr))*100);
            }else{
                val = parseInt(getStyle(obj, attr));
            }
            
            var speed = (json[attr] - val)/5;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            if(val == json[attr]){
                // 一旦发现json的某个属性到达目的地，就把定时器关了，这里有问题
                clearInterval(obj.timer);
                if(fnEnd) fnEnd();
            }else{
                if(attr == 'opacity'){
                    obj.style.filter = 'alpha(opacity:'+(val + speed)+')';
                    obj.style.opacity = (val + speed)/100;
                }else{
                    obj.style[attr] = val + speed + 'px';
                }
            }
        }

    }, 30);
}


//完美运动框架usage:  movePerfect(oDiv, {"width":400, "height":400}, function(){....});
// 等所有属性都到达目的地，关闭定时器
// 如果没有属性不到目的的，关闭定时器（在程序上更好实现）
function movePerfect2(obj, json, fnEnd){
    clearInterval(obj.timer);
    obj.timer = setInterval(function(){

        // 假设所有的值都已经到了
        var bStop = true;

        // json的循环用for-in
        for(var attr in json){

            var val = 0;
            if(attr == 'opacity'){
                val = Math.round(parseFloat(getStyle(obj, attr))*100);
            }else{
                val = parseInt(getStyle(obj, attr));
            }
            
            var speed = (json[attr] - val)/5;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

            if(val != json[attr]){
                bStop = false;
            }

            if(attr == 'opacity'){
                obj.style.filter = 'alpha(opacity:'+(val + speed)+')';
                obj.style.opacity = (val + speed)/100;
            }else{
                obj.style[attr] = val + speed + 'px';
            }
        }

        if(bStop){
            clearInterval(obj.timer);
            if(fnEnd) fnEnd();
        }

    }, 30);
}


function move(obj, attr, iTarget, fnEnd){
    clearInterval(obj.timer);
    obj.timer = setInterval(function(){
        var val = 0;
        if(attr == 'opacity'){
            val = Math.round(parseFloat(getStyle(obj, attr))*100);
        }else{
            val = parseInt(getStyle(obj, attr));
        }
        
        var speed = (iTarget - val)/5;
        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
        if(val == iTarget){
            clearInterval(obj.timer);
            if(fnEnd) fnEnd();
        }else{
            if(attr == 'opacity'){
                obj.style.filter = 'alpha(opacity:'+(val + speed)+')';
                obj.style.opacity = (val + speed)/100;
            }else{
                obj.style[attr] = val + speed + 'px';
            }
        }
    }, 30);
}

function getStyle(obj, name){
    if(obj.currentStyle){
        return obj.currentStyle[name];
    }
    else{
        return getComputedStyle(obj, null)[name];
    }
}

function getByClass(oParent, sClass){
    var aResult = [];
    var aEle = oParent.getElementsByTagName("*");
    for(var i=0; i<aEle.length; i++){
        if(aEle[i].className === sClass){
            aResult.push(aEle[i]);
        }
    }
    return aResult;
}


</script>
</body>
</html>